package com.wdb.modules.system.service.impl;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.wdb.exception.BadRequestException;
import com.wdb.exception.EntityExistException;
import com.wdb.modules.system.domain.Menu;
import com.wdb.modules.system.mapper.MenuMapper;
import com.wdb.modules.system.mapper.RoleMenuMapper;
import com.wdb.modules.system.service.RoleService;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.MockitoAnnotations;

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class MenuServiceImplTst {

    @InjectMocks
    private MenuServiceImpl menuService;

    @Mock
    private RoleService roleService;

    @Mock
    private MenuMapper menuMapper;

    @Mock
    private RoleMenuMapper roleMenuMapper;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(),""),Menu.class);
    }

    @Test(expected = BadRequestException.class)
    public void update_SelfReferencingParent_ThrowsBadRequestException() {
        Menu menu = new Menu();
        menu.setId(1L);
        menu.setPid(1L); // self-referencing

        menuService.update(menu);
    }

    @Test(expected = BadRequestException.class)
    public void update_InvalidUrlForIFrame_ThrowsBadRequestException() {
        Menu menu = new Menu();
        menu.setId(1L);
        menu.setIFrame(true);
        menu.setPath("ftp://invalid.url");

        menuService.update(menu);
    }

    @Test(expected = EntityExistException.class)
    public void update_TitleExistsForDifferentMenu_ThrowsEntityExistException() {
        Menu menu = new Menu();
        menu.setId(1L);
        menu.setTitle("ExistingTitle");

        when(menuMapper.findByTitle(anyString())).thenReturn(new Menu());

        menuService.update(menu);
    }

    @Test(expected = EntityExistException.class)
    public void update_ComponentNameExistsForDifferentMenu_ThrowsEntityExistException() {
        Menu menu = new Menu();
        menu.setId(1L);
        menu.setComponentName("ExistingComponentName");

        when(menuMapper.findByComponentName(anyString())).thenReturn(new Menu());

        menuService.update(menu);
    }

    @Test
    public void update_ValidMenu_UpdatesSuccessfully() {
        Menu menu = new Menu();
        menu.setId(1L);
        menu.setPid(null); // top-level menu
        menu.setIFrame(false);
        menu.setTitle("NewTitle");
        menu.setComponentName("NewComponentName");

        when(menuMapper.findByTitle(anyString())).thenReturn(null);
        when(menuMapper.findByComponentName(anyString())).thenReturn(null);

        doNothing().when(menuMapper).updateSubCntById(anyLong(), anyInt());

        menuService.update(menu);

        verify(menuMapper, times(1)).updateSubCntById(eq(0L), anyInt());
        verify(menuMapper, times(1)).updateSubCntById(eq(null), anyInt());
    }

    @Test
    public void update_ValidMenuWithNonZeroPid_UpdatesSuccessfully() {
        Menu menu = new Menu();
        menu.setId(1L);
        menu.setPid(2L); // valid parent ID
        menu.setIFrame(false);
        menu.setTitle("NewTitle");
        menu.setComponentName("NewComponentName");

        when(menuMapper.findByTitle(anyString())).thenReturn(null);
        when(menuMapper.findByComponentName(anyString())).thenReturn(null);

        doNothing().when(menuMapper).updateSubCntById(anyLong(), anyInt());

        menuService.update(menu);

        verify(menuMapper, times(1)).updateSubCntById(eq(2L), anyInt());
    }
}
